package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowTaskLogStatusEnum;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.feign.WorkflowDataProcessFeignClient;
import com.xbongbong.paas.help.WorkflowNodeHelp;
import com.xbongbong.paas.help.WorkflowRecordLogHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.pojo.workflow.BeforeOperatorPojo;
import com.xbongbong.paas.pojo.workflow.operate.dto.WorkflowAddSignatureDTO;
import com.xbongbong.paas.pojo.workflow.operate.dto.WorkflowApproveFailedDTO;
import com.xbongbong.paas.pojo.workflow.operate.dto.WorkflowCommitDTO;
import com.xbongbong.paas.pojo.workflow.operate.dto.WorkflowStorageDTO;
import com.xbongbong.paas.pojo.workflow.operate.dto.WorkflowTransferDTO;
import com.xbongbong.paas.pojo.workflow.operate.dto.WorkflowUpdateBackDTO;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowNodeConditionTypeEnum;
import com.xbongbong.paas.service.WorkflowApprovalOperate;
import com.xbongbong.paas.service.dingtalkTodo.WorkflowDingtalkTodoService;
import com.xbongbong.paas.service.workflow.WorkflowDataService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.paas.util.WorkflowTaskUtil;
import com.xbongbong.parent.help.PushMessageHelp;
import com.xbongbong.pro.enums.RichTextEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workrecord.enums.WorkrecordResultEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.message.constant.ProcessPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.process.pojo.dto.WorkrecordTaskDTO;
import com.xbongbong.pro.process.pojo.dto.WorkrecordTaskOption;
import com.xbongbong.pro.process.pojo.dto.WorkrecordUpdateTaskDTO;
import com.xbongbong.pro.service.dingtalk.WorkflowDingtalkService;
import com.xbongbong.pro.service.toolbox.data.ProFormDataHelp;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.SignTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskLogEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskLogItemEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.model.WorkflowDataChangeRecordModel;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskLogItemModel;
import com.xbongbong.workflow.model.WorkflowTaskLogModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.WorkflowRabbitmqDTO;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.changerecord.ChangeRecordMidPojo;
import com.xbongbong.workflow.pojo.nodes.ConditionNode;
import com.xbongbong.workflow.producer.WorkflowProducer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 吴峰
 * @date 2022/08/22 19:00
 */
@Slf4j
@Service("workflowApprovalOperate")
public class WorkflowApprovalOperateImpl implements WorkflowApprovalOperate {

    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private UserModel userModel;
    @Resource
    private WorkflowDingtalkTodoService workflowDingtalkTodoService;
    @Resource
    private WorkflowDingtalkService workflowDingtalkService;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private WorkflowTaskLogItemModel workflowTaskLogItemModel;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PushMessageHelp pushMessageHelp;
    @Resource
    private ProFormDataHelp proFormDataHelp;
    @Resource
    private MessageService messageService;
    @Resource
    private WorkflowProducer workflowProducer;
    @Resource
    private WorkflowTaskLogModel workflowTaskLogModel;
    @Resource
    private WorkflowDataService workflowDataService;
    @Resource
    private WorkflowDataProcessFeignClient workflowDataProcessFeignClient;
    @Resource
    private WorkflowNodeHelp workflowNodeHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkflowDataChangeRecordModel workflowDataChangeRecordModel;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private WorkflowRecordLogHelp workflowRecordLogHelp;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;

    @Override
    public void commit(WorkflowCommitDTO workflowCommitDTO, WorkflowTaskNodeEntity taskNodeEntity, BeforeOperatorPojo beforeOperatorPojo, WorkflowTransferDataEntity workflowTransferDataEntity) throws XbbException {
        String corpid = taskNodeEntity.getCorpid();
        // 当前节点处理
        taskNodeEntity.setTaskType(TaskTypeEnum.COMMIT.getType());
        workflowTaskNodeModel.update(taskNodeEntity);
        // 审批通过后，将主流程改成审批中；同意操作，需要将主任务置为“审批中”，否则无法控制“撤回”按钮
        workflowTaskModel.updateFlowStatusByTaskId(corpid, taskNodeEntity.getTaskId(), FlowStatusEnum.IN_APPROVAL.getType());
        // 其他节点处理，会签/或签
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.APPID, taskNodeEntity.getAppId());
        param.put(ParameterConstant.FORMID, taskNodeEntity.getFormId());
        param.put(ParameterConstant.MENUID, taskNodeEntity.getMenuId());
        param.put("workflowId", taskNodeEntity.getWorkflowId());
        param.put("workflowNodeId", taskNodeEntity.getWorkflowNodeId());
        param.put("taskId", taskNodeEntity.getTaskId());
        param.put("taskType", TaskTypeEnum.UNTREATED.getType());
        // 操作后要倒序找出最新的节点，取消钉钉待办节点任务
        param.put("orderByStr", " id DESC ");
        List<WorkflowTaskNodeEntity> workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(param);


        // 是否审批继续流转到下一个节点
        boolean isUpdateData = true;
        WorkflowTaskNodeEntity workflowTaskNodeEntity = null;
        if (Objects.nonNull(workflowTaskNodeEntities)) {

            if (Objects.equals(SignTypeEnum.ORSIGN.getValue(), taskNodeEntity.getSignType())) {
                // 或签
                workflowTaskNodeEntities.forEach(v -> {
                    v.setTaskType(TaskTypeEnum.OTHER_COMMIT.getType());
                });
                if (!workflowTaskNodeEntities.isEmpty()) {
                    // 在这里进行赋值，拿到最后一个，对后面待办有用
                    workflowTaskNodeEntity = workflowTaskNodeEntities.get(0);
                    workflowTaskNodeModel.updateBatch(workflowTaskNodeEntities, corpid);
                }
            } else {
                // 会签
                if (workflowTaskNodeEntities.size() > 0) {
                    // 还有其他审批节点，不用处理主数据表的状态,保持审批中状态
                    isUpdateData = false;
                }
            }
        }
        // 更新待抄送节点变为抄送节点
        param.put("taskType", TaskTypeEnum.WAIT_CC.getType());
        workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(param);

        // 当前节点
        WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(taskNodeEntity.getWorkflowNodeId(), corpid);

        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(workflowTransferDataEntity.getData().toJSONString(), WorkflowTransferPOJO.class);

        if (Objects.nonNull(workflowTaskNodeEntities) && !workflowTaskNodeEntities.isEmpty()) {
            Set<String> userIds = new HashSet<>();
            workflowTaskNodeEntities.forEach(v -> {
                v.setTaskType(TaskTypeEnum.CC.getType());
                userIds.add(v.getUserId());
            });
            workflowTaskNodeModel.updateBatch(workflowTaskNodeEntities, corpid);

            // 推送抄送消息
            String formName;
            if (Objects.equals(workflowNodeEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(workflowNodeEntity.getFormId(), corpid);
                formName = workOrderFormEntityExt.getName();
            } else {
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(workflowNodeEntity.getFormId(), corpid);
                formName = paasFormEntityExt.getName();
            }

            // 获取用户容器
            Map<String, Object> parmas = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            parmas.put("corpid", workflowNodeEntity.getCorpid());
            parmas.put("del", 0);
            List<UserEntity> userList = userModel.findEntitys(parmas);
            if (userList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            Map<String, UserEntity> userMap = new HashMap<>(userList.size());
            userList.forEach((item) -> userMap.put(item.getUserId(), item));
            // 获取部门容器
            parmas.remove(ParameterConstant.COLUMNS);
            List<DepartmentEntity> departmentList = departmentModel.findEntitys(parmas);
            if (departmentList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DEPT_NOT_EXIST);
            }
            Map<String, DepartmentEntity> departmentMap = new HashMap<>(departmentList.size());
            departmentList.forEach((departmentItem) -> departmentMap.put(departmentItem.getId().toString(), departmentItem));

            JSONObject dataJson = workflowTransferPOJO.getData().getData();
            PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
            paasProcessDataEntity.setAppId(workflowNodeEntity.getAppId());
            paasProcessDataEntity.setFormId(workflowNodeEntity.getFormId());
            paasProcessDataEntity.setMenuId(workflowNodeEntity.getMenuId());
            paasProcessDataEntity.setCorpid(workflowNodeEntity.getCorpid());
            paasProcessDataEntity.setId(workflowTransferPOJO.getData().getId());
            paasProcessDataEntity.setFormDataId(workflowTransferPOJO.getData().getId());
            paasProcessDataEntity.setSaasMark(workflowNodeEntity.getSaasMark());
            paasProcessDataEntity.setBusinessType(workflowNodeEntity.getBusinessType());
            paasProcessDataEntity.setData(dataJson.toJSONString());
            paasProcessDataEntity.setSerialNo(dataJson.getString(FieldTypeEnum.SERIALNO.getAlias()));
            paasProcessDataEntity.setOwnerId(dataJson.getString(FieldTypeEnum.OWNERID.getAlias()));
            paasProcessDataEntity.setAddTime(dataJson.getLong(FieldTypeEnum.ADDTIME.getAlias()));
            paasProcessDataEntity.setUpdateTime(dataJson.getLong(FieldTypeEnum.UPDATETIME.getAlias()));

            BaseDTO baseDTO = new BaseDTO();
            baseDTO.setCorpid(workflowNodeEntity.getCorpid());
            String content = pushMessageHelp.getMessageContent(paasProcessDataEntity, userMap, departmentMap, baseDTO);

            PushRefTypePojo.Options options = new PushRefTypePojo.Options(taskNodeEntity.getAppId(), taskNodeEntity.getMenuId(), taskNodeEntity.getFormId(), Collections.singletonList(taskNodeEntity.getDataId()), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(), taskNodeEntity.getTaskId(), taskNodeEntity.getId(), ProcessTypeEnum.CC.getValue());
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, new ArrayList<>(userIds), Collections.singletonList(taskNodeEntity.getTaskId()), 0, DateTimeUtil.getInt(), I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_CARBON_COPY_TITLE), String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_CARBON_COPY_CONTENT), workflowTransferPOJO.getUser().getName(), formName, content), null, options);
            messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.APPROVAL_CARBON_COPY_PUSH);

        }

        // 通过，继续执行下面的，更新主数据表的状态,以及其他关联数据表，父子审批，产品等
        if (isUpdateData) {
            // 更新数据
            PaasFormDataEntity paasFormDataEntity = null;
            if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                paasFormDataEntity = proFormDataHelp.getFormData(corpid, workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(), workflowTransferPOJO.getData().getId());
                JSONObject data = (JSONObject) CloneUtil.deepClone(workflowTransferPOJO.getData().getData());
                data.putAll(paasFormDataEntity.getData());
                paasFormDataEntity.setData(data);
            }
            update(workflowTransferPOJO, taskNodeEntity, beforeOperatorPojo, workflowCommitDTO.getLoginUser(), workflowTransferDataEntity);
            if (Objects.nonNull(paasFormDataEntity)) {
                FormDataUtil.setSystemData(paasFormDataEntity.getData(), paasFormDataEntity);
                Data oldData = new Data(workflowNodeEntity.getAppId(), workflowNodeEntity.getMenuId(), workflowNodeEntity.getFormId(), paasFormDataEntity.getId(),
                        paasFormDataEntity.getData(), workflowNodeEntity.getBusinessType(), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getId(), workflowTransferPOJO.getData().getSubBusinessType());
                workflowTransferPOJO.setOldData(oldData);
            }
            // 工作流发起继续执行
            WorkflowRabbitmqDTO workflowRabbitmqDTO = new WorkflowRabbitmqDTO(workflowTransferPOJO, workflowNodeEntity, beforeOperatorPojo.getSaasNeedRedundantAttrPojo());

            if (Objects.equals(corpid, "ding5de8f3770e040f5535c2f4657eb6378f")) {
                log.warn("workflow send operator message mulitple, message body===" + JSON.toJSONString(workflowRabbitmqDTO));
            }
            //更新当事人的钉钉状态为agree
            dingtalkOperation(taskNodeEntity, WorkrecordResultEnum.AGREE);
            // 审批操作人id
            workflowRabbitmqDTO.setOperatorId(workflowCommitDTO.getUserId());
            workflowProducer.startOperatorWorkflow(workflowRabbitmqDTO);

            // 更新logNode的状态
            WorkflowTaskLogEntity workflowTaskLogEntity = new WorkflowTaskLogEntity();
            workflowTaskLogEntity.setId(workflowTransferDataEntity.getLogId());
            workflowTaskLogEntity.setCorpid(corpid);
            workflowTaskLogEntity.setStatus(WorkflowTaskLogStatusEnum.PASS.getType());
            workflowTaskLogEntity.setContent(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_PAAS_APPROVE));
            workflowTaskLogEntity.setExitTime(DateTimeUtil.getInt());
            workflowTaskLogModel.update(workflowTaskLogEntity);

            WorkflowTaskLogItemEntity workflowTaskLogItemEntity = workflowTaskLogItemModel.getByLogIdNodeIdOrderByAddTime(corpid, workflowTransferDataEntity.getLogId(), workflowNodeEntity.getId());
            workflowTaskLogItemEntity.setStatus(WorkflowTaskLogStatusEnum.PASS.getType());
            workflowTaskLogItemEntity.setContent(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_PAAS_APPROVE));
            workflowTaskLogItemEntity.setUpdateTime(DateTimeUtil.getInt());
            workflowTaskLogItemEntity.setExitTime(DateTimeUtil.getInt());
            workflowTaskLogItemModel.update(workflowTaskLogItemEntity);
        } else {
            // 更新数据
            update(workflowTransferPOJO, taskNodeEntity, beforeOperatorPojo, workflowCommitDTO.getLoginUser(), workflowTransferDataEntity);

            workflowTransferDataEntity.setData(JSON.parseObject(JSON.toJSONString(workflowTransferPOJO, SerializerFeature.DisableCircularReferenceDetect)));
            workflowTransferDataModel.update(workflowTransferDataEntity);

            //更新当事人的钉钉状态为agree
            dingtalkOperation(taskNodeEntity, WorkrecordResultEnum.AGREE);
        }


        WorkflowTaskNodeEntity finalWorkflowTaskNodeEntity = workflowTaskNodeEntity;
        Runnable runnable = () -> {


            //或签处理
            if (SignTypeEnum.ORSIGN.getValue().equals(taskNodeEntity.getSignType()) && Objects.nonNull(finalWorkflowTaskNodeEntity)) {
                //取消其他节点的审批状态
                cancelDingtalkTaskGroup(finalWorkflowTaskNodeEntity);

            }
        };

        threadPoolBeanConfig.dingtalkTodo().execute(runnable);


    }

    @Override
    public void refuse(WorkflowTaskNodeEntity taskNodeEntity, boolean autoRefuse, WorkflowTransferPOJO workflowTransferPOJO, UserVO userVO) throws XbbException {
        // taskNode 处理
        Long taskId = taskNodeEntity.getTaskId();
        String corpid = taskNodeEntity.getCorpid();

        List<WorkflowTaskNodeEntity> updateTaskNodeList = new ArrayList<>();
        taskNodeEntity.setTaskType(TaskTypeEnum.END.getType());

        updateTaskNodeList.add(taskNodeEntity);

        // 处理其他taskNode
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        //param.put("workflowNodeId", taskNodeEntity.getWorkflowNodeId());
        param.put("taskId", taskId);
        param.put("taskTypeIn", Arrays.asList(TaskTypeEnum.UNTREATED.getType(), TaskTypeEnum.COMMIT.getType(), TaskTypeEnum.BACK.getType(), TaskTypeEnum.END.getType()));
        param.put(ParameterConstant.ORDER_BY_STR, "id desc");
        List<WorkflowTaskNodeEntity> allTaskNodeList = workflowTaskNodeModel.findEntities(param);
        List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList = allTaskNodeList.stream().filter(v -> Objects.equals(v.getWorkflowNodeId(), taskNodeEntity.getWorkflowNodeId())).collect(Collectors.toList());
        if (Objects.isNull(workflowTaskNodeEntityList)) {
            // TODO: 2021/5/26
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
        }
        Long recentBackTime = 0L;
        List<WorkflowTaskNodeEntity> backNodeList = allTaskNodeList.stream().filter(v -> Objects.equals(v.getTaskType(), TaskTypeEnum.BACK.getType())).collect(Collectors.toList());
        if(CollectionsUtil.isNotEmpty(backNodeList)){
            recentBackTime = backNodeList.get(0).getUpdateTime();
        }
        //只需要改当前审批节点的其他节点为他人同意，过滤下回退的情况，不然会影响到后面审批记录的展示
        Long finalRecentBackTime = recentBackTime;
        workflowTaskNodeEntityList.forEach(v -> {
            if(v.getAddTime() >= finalRecentBackTime){
                if (!Objects.equals(v.getId(), taskNodeEntity.getId())) {
                    v.setTaskType(TaskTypeEnum.OTHER_COMMIT.getType());
                    updateTaskNodeList.add(v);
                }
            }
        });

        if (!updateTaskNodeList.isEmpty()) {
            workflowTaskNodeModel.updateBatch(updateTaskNodeList, corpid);
        }

        // task 处理
        WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(taskId, corpid);
        workflowTaskEntity.setFlowStatus(FlowStatusEnum.REJECT.getType());
        workflowTaskModel.update(workflowTaskEntity);
        if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.ADD.getType())) {
            // 新建， 拒绝时删除主数据
            Integer businessType = XbbRefTypeEnum.PAAS.getCode();
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), taskNodeEntity.getSaasMark())) {
                businessType = taskNodeEntity.getBusinessType();
            }
            WorkflowApproveFailedDTO workflowApproveFailedDTO = new WorkflowApproveFailedDTO(corpid, taskNodeEntity.getSaasMark(), businessType, taskId, workflowTransferPOJO, TaskTypeEnum.END.getType(), userVO, PlatFormEnum.INTERNAL.getValue());
           XbbResponse<BaseVO> xbbResponse =  workflowDataProcessFeignClient.approvalFailed(workflowApproveFailedDTO, LocaleContextHolder.getLocale().toString());
            if (!xbbResponse.isSuccess()) {
                throw new XbbException(xbbResponse.getCode(), xbbResponse.getMsg());
            }
        } else if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
            // 编辑（还原编辑进审批前数据）
            Integer businessType = XbbRefTypeEnum.PAAS.getCode();
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), taskNodeEntity.getSaasMark())) {
                businessType = taskNodeEntity.getBusinessType();
            }
            WorkflowUpdateBackDTO workflowUpdateBackDTO = new WorkflowUpdateBackDTO(corpid, taskNodeEntity.getSaasMark(), businessType, taskId, workflowTransferPOJO, userVO, PlatFormEnum.INTERNAL.getValue());
            XbbResponse<BaseVO> xbbResponse = workflowDataProcessFeignClient.updateBack(workflowUpdateBackDTO, LocaleContextHolder.getLocale().toString());
            if (!xbbResponse.isSuccess()) {
                throw new XbbException(xbbResponse.getCode(), xbbResponse.getMsg());
            }
        }

        UserEntity operateUserEntity = userModel.getByKey(taskNodeEntity.getUserId(), corpid);
        String operateUserName = operateUserEntity == null ? "" : operateUserEntity.getName();

        // 更新logNode的状态
        // 当前节点
        WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(taskNodeEntity.getWorkflowNodeId(), corpid);
        WorkflowTaskLogEntity workflowTaskLogEntity = workflowTaskLogModel.getByTaskid(taskNodeEntity.getTaskId(), corpid);
        workflowTaskLogEntity.setStatus(WorkflowTaskLogStatusEnum.SUSPEND.getType());
        if (autoRefuse) {
            workflowTaskLogEntity.setContent(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_AUTO_REFUSE_APPROVE));
        } else {
            workflowTaskLogEntity.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_REFUSE_APPROVE), operateUserName));
        }
        workflowTaskLogEntity.setUpdateTime(DateTimeUtil.getInt());
        workflowTaskLogEntity.setExitTime(DateTimeUtil.getInt());
        workflowTaskLogModel.update(workflowTaskLogEntity);

        WorkflowTaskLogItemEntity workflowTaskLogItemEntity = workflowTaskLogItemModel.getByLogIdNodeIdOrderByAddTime(corpid, workflowTaskLogEntity.getId(), workflowNodeEntity.getId());
        workflowTaskLogItemEntity.setStatus(WorkflowTaskLogStatusEnum.SUSPEND.getType());
        if (autoRefuse) {
            workflowTaskLogItemEntity.setContent(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_AUTO_REFUSE_APPROVE));
        } else {
            workflowTaskLogItemEntity.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_REFUSE_APPROVE), operateUserName));
        }
        workflowTaskLogItemEntity.setUpdateTime(DateTimeUtil.getInt());
        workflowTaskLogItemEntity.setExitTime(DateTimeUtil.getInt());
        workflowTaskLogItemModel.update(workflowTaskLogItemEntity);

        // 中间上下文处理，拒绝删除上下文
        workflowTransferDataModel.deleteByTaskId(taskId, corpid);
        // 需要判断下一节点是否是分支节点，如果是分支节点，则需要判断是否含有审批通过或者审批拒绝的条件分支，如果有则需要继续执行工作流；反之，则不需要执行
        boolean startWorkflow = false;
        List<WorkflowNodeEntity> nextNodeList = workflowNodeModel.getByWorkflowIdAndPrevId(workflowNodeEntity.getWorkflowId(), workflowNodeEntity.getUid(), corpid);
        if (CollectionsUtil.isNotEmpty(nextNodeList)) {
            WorkflowNodeEntity next = nextNodeList.get(0);
            if (Objects.equals(WorkflowNodeTypeEnum.CONDITION_BLOCK_NODE.getType(), next.getType())) {
                List<WorkflowNodeEntity> conditionNodeList = workflowNodeModel.getByWorkflowIdAndPrevId(workflowNodeEntity.getWorkflowId(), next.getUid(), corpid);
                for (WorkflowNodeEntity item : conditionNodeList) {
                    ConditionNode conditionNode = workflowNodeHelp.getConditionNode(item);
                    if (Objects.equals(conditionNode.getConditionType(), WorkflowNodeConditionTypeEnum.APPROVAL_PAAS.getType())) {
                        startWorkflow = true;
                    } else if (Objects.equals(conditionNode.getConditionType(), WorkflowNodeConditionTypeEnum.APPROVAL_REFUSE.getType())) {
                        startWorkflow = true;
                    }
                }
            }
        }
        // 如果是审批结果分支，走拒绝逻辑，需要手动发起工作流
        if (startWorkflow) {
            workflowTransferPOJO.setRefuseFlag(true);
            WorkflowRabbitmqDTO workflowRabbitmqDTO = new WorkflowRabbitmqDTO(workflowTransferPOJO, workflowNodeEntity, null);
            workflowProducer.startOperatorWorkflow(workflowRabbitmqDTO);
        }


        if (CollectionsUtil.isNotEmpty(workflowTaskNodeEntityList)) {
            WorkflowTaskNodeEntity workflowTaskNodeEntity = workflowTaskNodeEntityList.get(0);
            if (Objects.nonNull(workflowTaskNodeEntity)) {
                //取消taskGroup任务,更新实例为拒绝
                Runnable runnable = () -> {
                    //取消dingtalk taskGroup
                    cancelDingtalkTaskGroup(workflowTaskNodeEntity);
                    //更新实例的状态为 拒绝
                    updateDingtalkInstanceStatus(workflowTaskEntity.getDingtalkProcessInstanceId(), workflowTaskEntity.getCorpid(), WorkrecordResultEnum.REFUSE);
                    pushDingtalkOAMessage(taskNodeEntity,workflowTransferPOJO);
                };

                threadPoolBeanConfig.dingtalkTodo().execute(runnable);
            }
        }
    }

    @Override
    public void storage(WorkflowStorageDTO workflowStorageDTO, WorkflowTaskNodeEntity workflowTaskNodeEntity, BeforeOperatorPojo beforeOperatorPojo, WorkflowTransferDataEntity workflowTransferDataEntity) throws XbbException {
        // 暂存只做数据存储，不流转
        try {
            String corpid = workflowStorageDTO.getCorpid();
            WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(workflowTransferDataEntity.getData().toJSONString(), WorkflowTransferPOJO.class);

            update(workflowTransferPOJO, workflowTaskNodeEntity, beforeOperatorPojo, workflowStorageDTO.getLoginUser(), workflowTransferDataEntity);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("WorkflowNodeApproveStrategy.storage error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void transfer(WorkflowTransferDTO workflowTransferDTO, WorkflowTaskNodeEntity taskNodeEntity, String transferUserId, BeforeOperatorPojo beforeOperatorPojo, WorkflowTransferDataEntity workflowTransferDataEntity) throws XbbException {
        String corpid = taskNodeEntity.getCorpid();

        // 当前转交人已经在该节点有审批节点就报错
        Map<String, Object> params = new HashMap<>();
        params.put(ParameterConstant.CORPID, corpid);
        params.put("taskId", taskNodeEntity.getTaskId());
        params.put(ParameterConstant.USER_ID, transferUserId);
        params.put("templateNodeId", taskNodeEntity.getWorkflowNodeId());
        params.put("taskType", TaskTypeEnum.UNTREATED.getType());
        params.put("del", 0);
        Integer count = workflowTaskNodeModel.getEntityCount(params);
        if (count > 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.TRANSFER_USER_NOT_TO_SAME);
        }


        // 处理当前节点的状态
        taskNodeEntity.setTaskType(TaskTypeEnum.TRANSFER.getType());
        workflowTaskNodeModel.update(taskNodeEntity);

        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getData(), SerializerFeature.DisableCircularReferenceDetect), WorkflowTransferPOJO.class);
        Data pojoData = workflowTransferPOJO.getData();

        // 生成新的taskNode转交后节点
        UserEntity user = userModel.getByKey(transferUserId, corpid);
        long now = DateTimeUtil.getInt();
        WorkflowTaskNodeEntity workflowTaskNodeEntity = new WorkflowTaskNodeEntity();
        workflowTaskNodeEntity.setCorpid(taskNodeEntity.getCorpid());
        workflowTaskNodeEntity.setAppId(taskNodeEntity.getAppId());
        workflowTaskNodeEntity.setFormId(taskNodeEntity.getFormId());
        workflowTaskNodeEntity.setMenuId(taskNodeEntity.getMenuId());
        workflowTaskNodeEntity.setSaasMark(taskNodeEntity.getSaasMark());
        workflowTaskNodeEntity.setBusinessType(taskNodeEntity.getBusinessType());
        workflowTaskNodeEntity.setWorkflowId(taskNodeEntity.getWorkflowId());
        workflowTaskNodeEntity.setTaskId(taskNodeEntity.getTaskId());
        workflowTaskNodeEntity.setDataId(taskNodeEntity.getDataId());
        workflowTaskNodeEntity.setTaskType(TaskTypeEnum.UNTREATED.getType());
        workflowTaskNodeEntity.setSignType(taskNodeEntity.getSignType());
        workflowTaskNodeEntity.setNodeType(taskNodeEntity.getNodeType());
        workflowTaskNodeEntity.setLastNodeId(taskNodeEntity.getLastNodeId());
        workflowTaskNodeEntity.setWorkflowNodeId(taskNodeEntity.getWorkflowNodeId());
        workflowTaskNodeEntity.setOpinion("");
        workflowTaskNodeEntity.setImages("");
        workflowTaskNodeEntity.setAttachment("");
        workflowTaskNodeEntity.setTransferUserId("");
        workflowTaskNodeEntity.setRevokeUserId("");
        workflowTaskNodeEntity.setBackspaceNode(0L);
        workflowTaskNodeEntity.setIsRead(0);
        workflowTaskNodeEntity.setAddTime(now);
        workflowTaskNodeEntity.setUpdateTime(now);
        workflowTaskNodeEntity.setDel(DelEnum.NORMAL.getDel());
        workflowTaskNodeEntity.setSerialNo(pojoData.getData().getString("serialNo") == null ?  "" : pojoData.getData().getString("serialNo"));

        if (Objects.isNull(user)) {
            // TODO: 2021/5/26
            // 转交人为空（离职），改为系统转交（老代码逻辑，我不知道为什么会这样，感觉是废代码，但是先保留）
            workflowTaskNodeEntity.setUserId(PaasConstant.SYS_USER_ID);
        } else {
            workflowTaskNodeEntity.setUserId(transferUserId);
        }

        workflowTaskNodeModel.insert(workflowTaskNodeEntity);

        // 转交也要更新数据
        update(workflowTransferPOJO, taskNodeEntity, beforeOperatorPojo, workflowTransferDTO.getLoginUser(), workflowTransferDataEntity);

        Runnable runnable = () -> {
            //将原有人的钉钉任务更新为 取消
            dingtalkOperation(taskNodeEntity, WorkrecordResultEnum.CANCELED);
            //为转交人创建钉钉任务
            if (!Objects.equals(workflowTaskNodeEntity.getUserId(), PaasConstant.SYS_USER_ID)) {
                createDingtalkTodoTask(Collections.singletonList(workflowTaskNodeEntity));
            }
        };

        threadPoolBeanConfig.dingtalkTodo().execute(runnable);

        WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(taskNodeEntity.getWorkflowNodeId(), corpid);
        WorkflowTaskLogEntity workflowTaskLogEntity = workflowTaskLogModel.getByTaskid(taskNodeEntity.getTaskId(), corpid);
        workflowTaskLogEntity.setStatus(WorkflowTaskLogStatusEnum.WAIT.getType());
        workflowTaskLogEntity.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_WAIT_APPROVE), Objects.nonNull(user) ? user.getName() : ""));
        workflowTaskLogEntity.setUpdateTime(DateTimeUtil.getInt());
        workflowTaskLogModel.update(workflowTaskLogEntity);

        WorkflowTaskLogItemEntity workflowTaskLogItemEntity = workflowTaskLogItemModel.getByLogIdNodeIdOrderByAddTime(corpid, workflowTaskLogEntity.getId(), workflowNodeEntity.getId());
        workflowTaskLogItemEntity.setStatus(WorkflowTaskLogStatusEnum.PASS.getType());
        workflowTaskLogItemEntity.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_TRANSFER_APPROVE), Objects.nonNull(user) ? user.getName() : ""));
        workflowTaskLogItemEntity.setUpdateTime(DateTimeUtil.getInt());
        workflowTaskLogItemEntity.setExitTime(DateTimeUtil.getInt());
        workflowTaskLogItemModel.update(workflowTaskLogItemEntity);

        WorkflowTaskLogItemEntity workflowTaskLogItemTransferEntity = (WorkflowTaskLogItemEntity) CloneUtil.deepClone(workflowTaskLogItemEntity);
        workflowTaskLogItemTransferEntity.setId(null);
        workflowTaskLogItemTransferEntity.setStatus(WorkflowTaskLogStatusEnum.WAIT.getType());
        workflowTaskLogItemTransferEntity.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_WAIT_APPROVE), Objects.nonNull(user) ? user.getName() : ""));
        workflowTaskLogItemTransferEntity.setAddTime(DateTimeUtil.getInt());
        workflowTaskLogItemTransferEntity.setUpdateTime(DateTimeUtil.getInt());
        workflowTaskLogItemTransferEntity.setExitTime(0L);
        workflowTaskLogItemModel.insert(workflowTaskLogItemTransferEntity);
    }

    @Override
    public void back(WorkflowTaskNodeEntity workflowTaskNodeEntity, String operatorId, WorkflowNodeEntity backNode) throws XbbException {
        Long taskId = workflowTaskNodeEntity.getTaskId();
        // 工作流模板节点id
        Long workflowNodeId = workflowTaskNodeEntity.getWorkflowNodeId();
        String corpid = workflowTaskNodeEntity.getCorpid();

        // 上一节点
        if (Objects.isNull(backNode) || !Objects.equals(WorkflowNodeTypeEnum.APPROVE_NODE.getType(), backNode.getType())) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260064);
        }

        // 更新当前节点为回退状态
        workflowTaskNodeEntity.setTaskType(TaskTypeEnum.BACK.getType());
        workflowTaskNodeModel.update(workflowTaskNodeEntity);

        // 处理当前节点的其他数据
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("taskId", taskId);
        params.put("workflowNodeId", workflowNodeId);
        params.put("taskTypeIn", Arrays.asList(TaskTypeEnum.UNTREATED.getType(), TaskTypeEnum.COMMIT.getType(), TaskTypeEnum.BACK.getType(), TaskTypeEnum.END.getType()));
        // 回退操作后要倒序找出最新的节点，取消钉钉待办节点任务
        params.put(ParameterConstant.ORDER_BY_STR, " id DESC ");
        List<WorkflowTaskNodeEntity> workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(params);
        if (CollectionUtils.isEmpty(workflowTaskNodeEntities)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
        }
        // 回退时，不管节点是会签还是或签，都将其他人的状态改成其他人同意
        List<WorkflowTaskNodeEntity> updateTaskNodeList = new ArrayList<>();
        workflowTaskNodeEntities.forEach(v -> {
            if (!Objects.equals(v.getUserId(), workflowTaskNodeEntity.getUserId()) && Objects.equals(TaskTypeEnum.UNTREATED.getType(), v.getTaskType())) {
                v.setTaskType(TaskTypeEnum.OTHER_COMMIT.getType());
                updateTaskNodeList.add(v);
            }
        });

        if (!CollectionUtils.isEmpty(updateTaskNodeList)) {
            workflowTaskNodeModel.updateBatch(updateTaskNodeList, corpid);
        }


        //钉钉工作台 取消其他节点的审批状态 取消taskGroup任务
        Runnable runnable = () -> {
            //取消dingtalk taskGroup
            cancelDingtalkTaskGroup(workflowTaskNodeEntity);
        };

        threadPoolBeanConfig.dingtalkTodo().execute(runnable);

        // 删除抄送任务
        params.clear();
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("taskId", taskId);
        params.put("workflowNodeId", workflowNodeId);
        params.put("taskType", TaskTypeEnum.WAIT_CC.getType());
        workflowTaskNodeEntities = workflowTaskNodeModel.findEntities(params);
        updateTaskNodeList.clear();
        workflowTaskNodeEntities.forEach(v -> {
            v.setDel(DelEnum.DELETE.getDel());
            updateTaskNodeList.add(v);
        });
        if (!CollectionUtils.isEmpty(updateTaskNodeList)) {
            workflowTaskNodeModel.updateBatch(updateTaskNodeList, corpid);
        }

        // 更新log
        WorkflowTaskLogEntity workflowTaskLogEntity = workflowTaskLogModel.getByTaskid(taskId, corpid);
        WorkflowTaskLogItemEntity workflowTaskLogItemEntity = workflowTaskLogItemModel.getByLogIdNodeIdOrderByAddTime(corpid, workflowTaskLogEntity.getId(), workflowNodeId);
        workflowTaskLogItemEntity.setStatus(WorkflowTaskLogStatusEnum.PASS.getType());

        UserEntity user = userModel.getByKeyIngoreDel(workflowTaskNodeEntity.getUserId(), corpid);
        String content = String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_BACK_APPROVE), user.getName());
        workflowTaskLogItemEntity.setContent(content);
        long now = DateTimeUtil.getInt();
        workflowTaskLogItemEntity.setExitTime(now);
        workflowTaskLogItemEntity.setUpdateTime(now);
        workflowTaskLogItemModel.update(workflowTaskLogItemEntity);


        // 创建新流程节点
//        WorkflowNodeEntity lastNode = workflowNodeModel.getByUId(workflowNodeEntity.getWorkflowId(), corpid, workflowNodeEntity.getPrevId());
//        WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(taskId, corpid);
//        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getData(), SerializerFeature.DisableCircularReferenceDetect), WorkflowTransferPOJO.class);
//        boolean isAutoApproval = createTaskNode(workflowTransferPOJO, workflowNodeEntity, lastNode.getId());
//        if (isAutoApproval) {
//            // 回退到上一个节点，如果上一个节点
//        }
        WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(taskId, corpid);
        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getData(), SerializerFeature.DisableCircularReferenceDetect), WorkflowTransferPOJO.class);
        SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getSaasNeedPojo(), SerializerFeature.DisableCircularReferenceDetect), SaasNeedRedundantAttrPojo.class);

        WorkflowRabbitmqDTO workflowRabbitmqDTO = new WorkflowRabbitmqDTO(workflowTransferPOJO, backNode, saasNeedRedundantAttrPojo);
        workflowRabbitmqDTO.setOperatorId(operatorId);
        workflowProducer.startWorkflow(workflowRabbitmqDTO);
    }

    @Override
    public void revoke(WorkflowTaskNodeEntity taskNodeEntity, String revokeUserId, UserVO userVO) throws XbbException {
        // 撤回taskNode
        Long taskId = taskNodeEntity.getTaskId();
        String corpid = taskNodeEntity.getCorpid();
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.APPID, taskNodeEntity.getAppId());
        param.put(ParameterConstant.FORMID, taskNodeEntity.getFormId());
        param.put(ParameterConstant.MENUID, taskNodeEntity.getMenuId());
        param.put("taskId", taskId);
        param.put(ParameterConstant.ORDER_BY_STR, "update_time asc, id asc");
        List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList = workflowTaskNodeModel.findEntities(param);
        if (Objects.isNull(workflowTaskNodeEntityList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
        }

        // 获取最新的提交节点
        WorkflowTaskNodeEntity startNode = new WorkflowTaskNodeEntity();
        for (WorkflowTaskNodeEntity workflowTaskNodeEntity : workflowTaskNodeEntityList) {
            if (WorkflowTaskUtil.isCreateTaskNode(workflowTaskNodeEntity)) {
                startNode = workflowTaskNodeEntity;
            }
        }

        List<WorkflowTaskNodeEntity> updateTaskNodeList = new ArrayList<>();
        startNode.setRevokeUserId(revokeUserId);
        startNode.setTaskType(TaskTypeEnum.REVOKE.getType());
        updateTaskNodeList.add(startNode);

        for (WorkflowTaskNodeEntity v : workflowTaskNodeEntityList) {
            if (v.getAddTime() >= startNode.getAddTime() && !startNode.getWorkflowNodeId().equals(v.getWorkflowNodeId())) {
                v.setRevokeUserId(revokeUserId);
                v.setDel(DelEnum.DELETE.getDel());
                v.setTaskType(TaskTypeEnum.REVOKE.getType());
                updateTaskNodeList.add(v);
            }
        }
        if (!updateTaskNodeList.isEmpty()) {
            workflowTaskNodeModel.updateBatch(updateTaskNodeList, corpid);
        }

        // 撤回task，更新主任务状态
        WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(taskId, corpid);
        workflowTaskEntity.setFlowStatus(FlowStatusEnum.REVOKE.getType());
        workflowTaskModel.update(workflowTaskEntity);

        // 更新主数据
        //  更新方法，撤回还要考虑新建数据和再次审批数据的不同处理
        WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(taskId, corpid);
        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getData(), SerializerFeature.DisableCircularReferenceDetect), WorkflowTransferPOJO.class);
        if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.ADD.getType())) {
            Integer businessType = XbbRefTypeEnum.PAAS.getCode();
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), taskNodeEntity.getSaasMark())) {
                businessType = taskNodeEntity.getBusinessType();
            }
            WorkflowApproveFailedDTO workflowApproveFailedDTO = new WorkflowApproveFailedDTO(corpid, taskNodeEntity.getSaasMark(), businessType, taskId, workflowTransferPOJO, TaskTypeEnum.REVOKE.getType(), userVO, PlatFormEnum.INTERNAL.getValue());
            XbbResponse<BaseVO> xbbResponse = workflowDataProcessFeignClient.approvalFailed(workflowApproveFailedDTO, LocaleContextHolder.getLocale().toString());
            if (!xbbResponse.isSuccess()) {
                throw new XbbException(xbbResponse.getCode(), xbbResponse.getMsg());
            }
        } else if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
            Integer businessType = XbbRefTypeEnum.PAAS.getCode();
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), taskNodeEntity.getSaasMark())) {
                businessType = taskNodeEntity.getBusinessType();
            }
            WorkflowUpdateBackDTO workflowUpdateBackDTO = new WorkflowUpdateBackDTO(corpid, taskNodeEntity.getSaasMark(), businessType, taskId, workflowTransferPOJO, userVO, PlatFormEnum.INTERNAL.getValue());
           XbbResponse<BaseVO> xbbResponse = workflowDataProcessFeignClient.updateBack(workflowUpdateBackDTO, LocaleContextHolder.getLocale().toString());
           if (!xbbResponse.isSuccess()) {
               throw new XbbException(xbbResponse.getCode(), xbbResponse.getMsg());
           }
        }

        UserEntity revokeUser = userModel.getByKey(revokeUserId, corpid);
        String revokeUserName = revokeUser == null ? "" : revokeUser.getName();

        // 更新logNode的状态
        // 当前节点
        WorkflowTaskLogEntity workflowTaskLogEntity = workflowTaskLogModel.getByTaskid(taskNodeEntity.getTaskId(), corpid);
        workflowTaskLogEntity.setStatus(WorkflowTaskLogStatusEnum.SUSPEND.getType());
        workflowTaskLogEntity.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_REVOKE_APPROVE), revokeUserName));
        workflowTaskLogEntity.setUpdateTime(DateTimeUtil.getInt());
        workflowTaskLogEntity.setExitTime(DateTimeUtil.getInt());
        workflowTaskLogModel.update(workflowTaskLogEntity);

        param.clear();
        param.put(ParameterConstant.CORPID, corpid);
        param.put("nodeType", WorkflowTaskLogStatusEnum.WAIT.getType());
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("workflowTaskLogId", workflowTaskLogEntity.getId());
        List<WorkflowTaskLogItemEntity> workflowTaskLogItemEntities = workflowTaskLogItemModel.findEntitys(param);
        workflowTaskLogItemEntities.forEach(v -> {
            v.setStatus(WorkflowTaskLogStatusEnum.SUSPEND.getType());
            v.setContent(String.format(I18nMessageUtil.getMessage(MessageConstant.WORKFLOW_NODE_REVOKE_APPROVE), revokeUserName));
            v.setUpdateTime(DateTimeUtil.getInt());
            v.setExitTime(DateTimeUtil.getInt());
        });
        if (!CollectionUtils.isEmpty(workflowTaskLogItemEntities)) {
            workflowTaskLogItemModel.updateBatch(workflowTaskLogItemEntities, corpid);
        }

        // 中间上下文处理，撤回删除上下文
        workflowTransferDataModel.deleteByTaskId(taskId, corpid);


        Runnable runnable = () -> updateDingtalkInstanceStatus(workflowTaskEntity.getDingtalkProcessInstanceId(), taskNodeEntity.getCorpid(), WorkrecordResultEnum.TERMINATED);

        threadPoolBeanConfig.dingtalkTodo().execute(runnable);
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, WorkflowTaskNodeEntity taskNodeEntity, BeforeOperatorPojo beforeOperatorPojo, UserVO userVO, WorkflowTransferDataEntity workflowTransferDataEntity) throws XbbException {
        Long clueId = workflowTransferPOJO.getData().getData().getLong("clueId");
        Long isBringCustomer = workflowTransferPOJO.getData().getData().getLong("isBringCustomer");
        String corpid = workflowTransferPOJO.getCorpid();
        PaasFormDataEntity paasFormDataEntity = proFormDataHelp.getFormData(corpid, taskNodeEntity.getSaasMark(), taskNodeEntity.getBusinessType(), taskNodeEntity.getDataId());
        JSONObject data = beforeOperatorPojo.getData();
        JSONObject originalOldData = workflowTransferPOJO.getData().getData();
        if (Objects.equals(corpid, "ding32a4e43fe882902335c2f4657eb6378f") && Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), workflowTransferDataEntity.getBusinessType())) {
            log.warn(taskNodeEntity.getCorpid() + ">>before>>" + JSON.toJSONString(beforeOperatorPojo.getData()));
        }
        if (Objects.nonNull(clueId)) {
            data.put("clueId", clueId);
        }
        if (Objects.nonNull(isBringCustomer)) {
            data.put("isBringCustomer", isBringCustomer);
        }
        //更新上下文流转数据,需删除富文本数据
        WorkflowTransferDataEntity update = new WorkflowTransferDataEntity();
        update.setTaskId(workflowTransferDataEntity.getTaskId());
        update.setId(workflowTransferDataEntity.getId());
        update.setCorpid(corpid);
        data.remove(RichTextEnum.RICH_TEXT.getAttr());
        workflowTransferPOJO.getData().setData(data);
        update.setData(JSON.parseObject(JSON.toJSONString(workflowTransferPOJO, SerializerFeature.DisableCircularReferenceDetect)));
        update.setSaasNeedPojo(JSON.parseObject(JSON.toJSONString(beforeOperatorPojo.getSaasNeedRedundantAttrPojo(), SerializerFeature.DisableCircularReferenceDetect)));
        update.setUpdateTime(DateTimeUtil.getInt());
        workflowTransferDataModel.update(update);
        // 更新主数据
        updateData(workflowTransferPOJO, taskNodeEntity, beforeOperatorPojo, userVO,TaskTypeEnum.COMMIT.getType());
        //每通过一个节点需要记录一下这次提交有无修改的内容，若有修改则需要记录到日志表中
        if (Objects.equals(WorkflowOperateEnum.UPDATE.getType(), workflowTransferPOJO.getOperate())) {
            ChangeRecordMidPojo changeRecordMidPojo = workflowRecordLogHelp.getChangeRecordMidPojo(workflowTransferPOJO);
            changeRecordMidPojo.setCorpid(taskNodeEntity.getCorpid());
            changeRecordMidPojo.setWorkflowTaskId(taskNodeEntity.getTaskId());
            changeRecordMidPojo.setWorkflowNodeId(taskNodeEntity.getId());
            changeRecordMidPojo.setUserVO(userVO);
            changeRecordMidPojo.setOriginalOldData(originalOldData);
            changeRecordMidPojo.setOriginalNewData(data);
            workflowRecordLogHelp.recordDataChange(changeRecordMidPojo);
        }
        if (Objects.equals(corpid, "ding32a4e43fe882902335c2f4657eb6378f") && Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), workflowTransferDataEntity.getBusinessType())) {
            log.warn(corpid + ">>after>>  " + JSON.toJSONString(beforeOperatorPojo.getData()));
        }
    }

    @Override
    public void updateData(WorkflowTransferPOJO workflowTransferPOJO, WorkflowTaskNodeEntity taskNodeEntity, BeforeOperatorPojo beforeOperatorPojo, UserVO userVO, Integer taskType) throws XbbException {
        String corpid = workflowTransferPOJO.getCorpid();
        JSONObject dataList = (JSONObject) CloneUtil.deepClone(beforeOperatorPojo.getData());

        FormDataUpdateDTO formDataUpdateDTO = new FormDataUpdateDTO(taskNodeEntity.getFormId(), taskNodeEntity.getAppId(), taskNodeEntity.getMenuId(), taskNodeEntity.getDataId(),
               dataList , taskNodeEntity.getSaasMark(), taskNodeEntity.getBusinessType(), taskNodeEntity.getBusinessType(),
                beforeOperatorPojo.getSaasNeedRedundantAttrPojo(), userVO, corpid, beforeOperatorPojo.getHttpHeader(), PlatFormEnum.INTERNAL.getValue());
        formDataUpdateDTO.setVisbleDept(beforeOperatorPojo.getVisbleDept());
        formDataUpdateDTO.setVisbleUser(beforeOperatorPojo.getVisbleUser());
        formDataUpdateDTO.setTaskType(taskType);
        workflowDataService.update(formDataUpdateDTO);
    }

    @Override
    public void createDingtalkTodoTask(List<WorkflowTaskNodeEntity> workflowTaskNodeEntityList) {
        if (CollectionsUtil.isEmpty(workflowTaskNodeEntityList)) {
            return;
        }
        WorkflowTaskNodeEntity taskNodeEntity = workflowTaskNodeEntityList.get(0);
        String corpid = taskNodeEntity.getCorpid();
        Long taskId = taskNodeEntity.getTaskId();
        //获取钉钉实例id
        WorkflowTaskEntity taskEntity = workflowTaskModel.getByKey(taskId, corpid);
        if (taskEntity == null) {
            return;
        }

        String dingtalkProcessInstanceId = taskEntity.getDingtalkProcessInstanceId();
        if (StringUtil.isEmpty(dingtalkProcessInstanceId)) {
            return;
        }

        WorkrecordTaskDTO workrecordTaskDTO = new WorkrecordTaskDTO();
        workrecordTaskDTO.setCorpid(taskEntity.getCorpid());
        workrecordTaskDTO.setDingtalkProcessInstanceId(dingtalkProcessInstanceId);
        List<WorkrecordTaskOption> taskOptions = new ArrayList<>();

        for (WorkflowTaskNodeEntity workflowTaskNodeEntity : workflowTaskNodeEntityList) {
            WorkrecordTaskOption taskOption = new WorkrecordTaskOption();
            // 审批人
            taskOption.setUserId(workflowTaskNodeEntity.getUserId());
            // 复用OA消息的 options = new PushRefTypePojo.Options(appId, menuId, formId, Collections.singletonList(dataId), saasMark, businessType, taskId, startNodeTask.getId(), ProcessTypeEnum.CREATE.getValue());
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(workflowTaskNodeEntity.getAppId(), workflowTaskNodeEntity.getMenuId(), workflowTaskNodeEntity.getFormId(), null,
                    taskEntity.getSaasMark(), taskEntity.getBusinessType(), workflowTaskNodeEntity.getTaskId(), workflowTaskNodeEntity.getId(), ProcessTypeEnum.TODO.getValue());
            taskOption.setOptions(options);
            taskOptions.add(taskOption);
        }

        workrecordTaskDTO.setTaskOptions(taskOptions);

        workflowDingtalkService.createDingtalkTask(workrecordTaskDTO);
    }

    /**
     * 更新钉钉待办实例状态
     * @param dingtalkProcessInstanceId
     * @param corpid
     * @param resultEnum 枚举实例状态
     */
    private void updateDingtalkInstanceStatus(String dingtalkProcessInstanceId, String corpid, WorkrecordResultEnum resultEnum) {
        if (StringUtil.isNotEmpty(dingtalkProcessInstanceId)) {
            workflowDingtalkService.updateDingtalkInstance(corpid, dingtalkProcessInstanceId, resultEnum);
        }
    }

    /**
     * 取消其他节点的审批状态
     * @param workflowTaskNodeEntity
     */
    private void cancelDingtalkTaskGroup(WorkflowTaskNodeEntity workflowTaskNodeEntity) {
        if (StringUtil.isNotEmpty(workflowTaskNodeEntity.getDingtalkWorkrecordActivityId())) {
            String corpid = workflowTaskNodeEntity.getCorpid();

            //找出同一审批节点下的所有ActivityId(Activity组)
            Map<String, Object> params = new HashMap<>(BasicConstant.FIVE);
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.FORM_ID, workflowTaskNodeEntity.getFormId());
            params.put(StringConstant.TASK_ID, workflowTaskNodeEntity.getTaskId());
            params.put(StringConstant.WORKFLOW_NODE_ID, workflowTaskNodeEntity.getWorkflowNodeId());
            params.put(StringConstant.COLUMNS, "dingtalk_workrecord_activity_id");
            List<String> activityIds = workflowTaskNodeModel.findEntities(params).stream()
                    .map(WorkflowTaskNodeEntity::getDingtalkWorkrecordActivityId).distinct().collect(Collectors.toList());

            //批量取消同一审批节点下的所有任务
            WorkrecordUpdateTaskDTO workrecordUpdateTaskDTO = new WorkrecordUpdateTaskDTO();
            workrecordUpdateTaskDTO.setCorpid(corpid);
            workrecordUpdateTaskDTO.setDingtalkInstanceId(workflowTaskNodeEntity.getDingtalkProcessInstanceId());
            workrecordUpdateTaskDTO.setDingtalkActivityId(workflowTaskNodeEntity.getDingtalkWorkrecordActivityId());
            workrecordUpdateTaskDTO.setDingtalkActivityIds(activityIds);
            workflowDingtalkService.batchCancelDingtalkTask(workrecordUpdateTaskDTO);
        }
    }


    /**
     * 按状态更新钉钉待办任务
     * 适用于 同意 和 转交
     * @param taskNodeEntity
     * @param resultEnum
     */
    private void dingtalkOperation(WorkflowTaskNodeEntity taskNodeEntity, WorkrecordResultEnum resultEnum) {
        String workrecordTaskId = taskNodeEntity.getDingtalkWorkrecordTaskId();
        if (StringUtil.isNotEmpty(workrecordTaskId)) {
            WorkrecordUpdateTaskDTO workrecordUpdateTaskDTO = new WorkrecordUpdateTaskDTO();
            workrecordUpdateTaskDTO.setCorpid(taskNodeEntity.getCorpid());
            workrecordUpdateTaskDTO.setDingtalkInstanceId(taskNodeEntity.getDingtalkProcessInstanceId());
            workrecordUpdateTaskDTO.setDingtalkTaskId(workrecordTaskId);
            workflowDingtalkService.updateDingtalkTask(workrecordUpdateTaskDTO, resultEnum);
        }
    }

    /**
     * 发送钉钉OA消息
     * @param taskNodeEntity
     * @param workflowTransferPOJO
     */
    private void pushDingtalkOAMessage(WorkflowTaskNodeEntity taskNodeEntity,WorkflowTransferPOJO workflowTransferPOJO){
        try {
            String corpid = taskNodeEntity.getCorpid();
            WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(taskNodeEntity.getWorkflowNodeId(), corpid);
            // 获取用户容器
            Map<String, Object> parmas = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            parmas.put("corpid", workflowNodeEntity.getCorpid());
            parmas.put("del", 0);
            List<UserEntity> userList = userModel.findEntitys(parmas);
            if (userList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            Map<String, UserEntity> userMap = new HashMap<>(userList.size());
            userList.forEach((item) -> userMap.put(item.getUserId(), item));
            // 获取部门容器
            parmas.remove(ParameterConstant.COLUMNS);
            parmas.put("del", 0);
            List<DepartmentEntity> departmentList = departmentModel.findEntitys(parmas);
            if (departmentList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DEPT_NOT_EXIST);
            }
            Map<String, DepartmentEntity> departmentMap = new HashMap<>(departmentList.size());
            departmentList.forEach((departmentItem) -> departmentMap.put(departmentItem.getId().toString(), departmentItem));

            JSONObject dataJson = workflowTransferPOJO.getData().getData();
            PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
            paasProcessDataEntity.setAppId(workflowNodeEntity.getAppId());
            paasProcessDataEntity.setFormId(workflowNodeEntity.getFormId());
            paasProcessDataEntity.setMenuId(workflowNodeEntity.getMenuId());
            paasProcessDataEntity.setCorpid(workflowNodeEntity.getCorpid());
            paasProcessDataEntity.setId(workflowTransferPOJO.getData().getId());
            paasProcessDataEntity.setFormDataId(workflowTransferPOJO.getData().getId());
            paasProcessDataEntity.setSaasMark(workflowNodeEntity.getSaasMark());
            paasProcessDataEntity.setBusinessType(workflowNodeEntity.getBusinessType());
            paasProcessDataEntity.setData(dataJson.toJSONString());
            paasProcessDataEntity.setSerialNo(dataJson.getString(FieldTypeEnum.SERIALNO.getAlias()));
            paasProcessDataEntity.setCreatorId(workflowTransferPOJO.getUser().getUserId());
            paasProcessDataEntity.setOwnerId(dataJson.getString(FieldTypeEnum.OWNERID.getAlias()));
            paasProcessDataEntity.setAddTime(dataJson.getLong(FieldTypeEnum.ADDTIME.getAlias()));
            paasProcessDataEntity.setUpdateTime(dataJson.getLong(FieldTypeEnum.UPDATETIME.getAlias()));

            BaseDTO baseDTO = new BaseDTO();
            baseDTO.setCorpid(workflowNodeEntity.getCorpid());
            String content = pushMessageHelp.getMessageContent(paasProcessDataEntity, userMap, departmentMap, baseDTO);
            String formName;
            if (Objects.equals(workflowNodeEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(workflowNodeEntity.getFormId(), corpid);
                formName = workOrderFormEntityExt.getName();
            } else {
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(workflowNodeEntity.getFormId(), corpid);
                formName = paasFormEntityExt.getName();
            }
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(taskNodeEntity.getAppId(), taskNodeEntity.getMenuId(), taskNodeEntity.getFormId(), Collections.singletonList(taskNodeEntity.getDataId()), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(), taskNodeEntity.getTaskId(), taskNodeEntity.getId(), ProcessTypeEnum.CREATE.getValue());
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, Collections.singletonList(paasProcessDataEntity.getCreatorId()), Collections.singletonList(taskNodeEntity.getDataId()), 0, DateTimeUtil.getInt(), I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_REFUSE_TITLE), String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_REFUSE_CONTENT), workflowTransferPOJO.getUser().getName(), formName, content), null, options);
            messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.APPROVAL_REFUSE_PUSH);
        }catch (XbbException e){
            log.error("WorkflowNodeApproveStrategy.pushDingtalkOAMessage Failure",e);
        }
    }

    @Override
    public void addSignature(WorkflowAddSignatureDTO workflowAddSignatureDTO, WorkflowTaskNodeEntity workflowTaskNodeEntity, List<WorkflowTaskNodeEntity> nowTaskNodeList) throws XbbException {
        Set<String> addUserIds = workflowAddSignatureDTO.getAddUserIds();
        Long taskId = workflowAddSignatureDTO.getProcessTaskId();
        String corpid = workflowAddSignatureDTO.getCorpid();

        WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(taskId, corpid);

        WorkflowTransferPOJO workflowTransferPOJO = JSON.parseObject(JSON.toJSONString(workflowTransferDataEntity.getData(), SerializerFeature.DisableCircularReferenceDetect), WorkflowTransferPOJO.class);

        WorkflowNodeEntity workflowNodeEntity = workflowNodeModel.getByKey(workflowTaskNodeEntity.getWorkflowNodeId(), corpid);
        if (Objects.isNull(workflowNodeEntity)) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260036);
        }

        if (CollectionsUtil.isNotEmpty(nowTaskNodeList)) {
            if (nowTaskNodeList.size() == BasicConstant.ONE) {
                // 当是单节点加签的实话，需要修改之前的signtype
                nowTaskNodeList.forEach(v -> v.setSignType(workflowAddSignatureDTO.getSignType()));
                workflowTaskNodeModel.updateBatch(nowTaskNodeList, corpid);
            }
        }

        List<WorkflowTaskNodeEntity> insertList = new ArrayList<>();
        long now = DateTimeUtil.getInt();
        for (String addUserId : addUserIds) {
            WorkflowTaskNodeEntity workflowTaskNode = new WorkflowTaskNodeEntity();
            workflowTaskNode.setCorpid(corpid);
            workflowTaskNode.setAppId(workflowTaskNodeEntity.getAppId());
            workflowTaskNode.setFormId(workflowTaskNodeEntity.getFormId());
            workflowTaskNode.setMenuId(workflowTaskNodeEntity.getMenuId());
            workflowTaskNode.setSaasMark(workflowTaskNodeEntity.getSaasMark());
            workflowTaskNode.setBusinessType(workflowTaskNodeEntity.getBusinessType());
            workflowTaskNode.setWorkflowId(workflowTaskNodeEntity.getWorkflowId());
            workflowTaskNode.setTaskId(workflowTaskNodeEntity.getTaskId());

            workflowTaskNode.setUserId(addUserId);
            workflowTaskNode.setDataId(workflowTaskNodeEntity.getDataId());
            workflowTaskNode.setTaskType(TaskTypeEnum.UNTREATED.getType());
            workflowTaskNode.setSignType(workflowAddSignatureDTO.getSignType());
            workflowTaskNode.setNodeType(workflowTaskNodeEntity.getNodeType());
            workflowTaskNode.setLastNodeId(workflowTaskNodeEntity.getLastNodeId());
            workflowTaskNode.setWorkflowNodeId(workflowTaskNodeEntity.getWorkflowNodeId());
            workflowTaskNode.setOpinion("");
            workflowTaskNode.setImages("");
            workflowTaskNode.setAttachment("");
            workflowTaskNode.setRevokeUserId("");
            workflowTaskNode.setBackspaceNode(0L);
            workflowTaskNode.setIsRead(BasicConstant.ZERO);
            workflowTaskNode.setAddTime(now);
            workflowTaskNode.setUpdateTime(now);
            workflowTaskNode.setDel(DelEnum.NORMAL.getDel());
            workflowTaskNode.setSerialNo(workflowTaskNodeEntity.getSerialNo());
            workflowTaskNode.setTransferUserId("");
            workflowTaskNode.setTitle(workflowTaskNodeEntity.getTitle());
            // 加签标记
            workflowTaskNode.setAddSignature(BasicConstant.ONE);
            insertList.add(workflowTaskNode);
        }

        if (CollectionsUtil.isNotEmpty(insertList)) {
            workflowTaskNodeModel.insertBatch(insertList);

            WorkflowTaskLogEntity workflowTaskLogEntity = workflowTaskLogModel.getByTaskid(workflowTaskNodeEntity.getTaskId(), corpid);

            WorkflowTaskLogItemEntity workflowTaskLogItemEntity = workflowTaskLogItemModel.getByLogIdNodeIdOrderByAddTime(corpid, workflowTaskLogEntity.getId(), workflowNodeEntity.getId());
            String contentStr = workflowTaskLogItemEntity.getContent();

            List<UserEntity> userEntities = userModel.getByUserIdIn(corpid, addUserIds, DelEnum.NORMAL.getDel());

            List<String> userNameList = new ArrayList<>();
            userEntities.forEach(userEntity -> userNameList.add(userEntity.getName()));
            String signUserName;
            if(userNameList.size() == 1){
                signUserName = userNameList.get(0) + StringConstant.COMMA;
            }else{
                signUserName = StringUtils.join(userNameList, StringConstant.COMMA);
            }

            workflowTaskLogItemEntity.setContent(signUserName + contentStr);
            workflowTaskLogItemModel.update(workflowTaskLogItemEntity);

            workflowTaskLogEntity.setContent(signUserName + contentStr);
            workflowTaskLogModel.update(workflowTaskLogEntity);


            // 发送钉钉代办
            Runnable runnable = () -> {
                try {
                    // 钉钉代办
                    createDingtalkTodoTask(insertList);

                    // 推送消息
                    PushRefTypePojo.Options options;
                    MessageRabbitMqDTO messageRabbitMqDTO;

                    String formName;
                    if (Objects.equals(workflowNodeEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                        WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(workflowNodeEntity.getFormId(), workflowNodeEntity.getCorpid());
                        formName = workOrderFormEntityExt.getName();
                    } else {
                        PaasFormEntity paasFormEntity = paasFormModel.getByKey(workflowNodeEntity.getFormId(), workflowNodeEntity.getCorpid());
                        formName = paasFormEntity.getName();
                    }
                    JSONObject dataJson = workflowTransferPOJO.getData().getData();
                    PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
                    paasProcessDataEntity.setAppId(workflowNodeEntity.getAppId());
                    paasProcessDataEntity.setFormId(workflowNodeEntity.getFormId());
                    paasProcessDataEntity.setMenuId(workflowNodeEntity.getMenuId());
                    paasProcessDataEntity.setCorpid(workflowNodeEntity.getCorpid());
                    paasProcessDataEntity.setId(workflowTransferPOJO.getData().getId());
                    paasProcessDataEntity.setFormDataId(workflowTransferPOJO.getData().getId());
                    paasProcessDataEntity.setSaasMark(workflowNodeEntity.getSaasMark());
                    paasProcessDataEntity.setBusinessType(workflowNodeEntity.getBusinessType());
                    paasProcessDataEntity.setData(dataJson.toJSONString());
                    paasProcessDataEntity.setSerialNo(dataJson.getString(FieldTypeEnum.SERIALNO.getAlias()));
                    paasProcessDataEntity.setOwnerId(dataJson.getString(FieldTypeEnum.OWNERID.getAlias()));
                    paasProcessDataEntity.setAddTime(dataJson.getLong(FieldTypeEnum.ADDTIME.getAlias()));
                    paasProcessDataEntity.setUpdateTime(dataJson.getLong(FieldTypeEnum.UPDATETIME.getAlias()));

                    // 获取用户容器
                    Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("corpid", corpid);
                    param.put("del", 0);
                    List<UserEntity> userList = userModel.findEntitys(param);
                    if (userList == null) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
                    }
                    Map<String, UserEntity> userMap = new HashMap<>(userList.size());
                    userList.forEach((item) -> userMap.put(item.getUserId(), item));
                    // 获取部门容器
                    param.remove(ParameterConstant.COLUMNS);
                    List<DepartmentEntity> departmentList = departmentModel.findEntitys(param);
                    if (departmentList == null) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DEPT_NOT_EXIST);
                    }
                    Map<String, DepartmentEntity> departmentMap = new HashMap<>(departmentList.size());
                    departmentList.forEach((departmentItem) -> departmentMap.put(departmentItem.getId().toString(), departmentItem));

                    BaseDTO baseDTO = new BaseDTO();
                    baseDTO.setCorpid(corpid);
                    String content = pushMessageHelp.getMessageContent(paasProcessDataEntity, userMap, departmentMap, baseDTO);

                    for (WorkflowTaskNodeEntity nodeEntity : insertList) {
                        options = new PushRefTypePojo.Options(workflowNodeEntity.getAppId(), workflowNodeEntity.getMenuId(), workflowNodeEntity.getFormId(),
                                Collections.singletonList(workflowTransferPOJO.getData().getId()), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(),
                                workflowTransferPOJO.getTaskId(), nodeEntity.getId(), ProcessTypeEnum.TODO.getValue());
                        messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, Collections.singletonList(nodeEntity.getUserId()), Collections.singletonList(nodeEntity.getTaskId()), 0, DateTimeUtil.getInt(), I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_NODE_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_ADD_CONTENT), workflowTransferPOJO.getUser().getName(), formName, content), null, options);
                        messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.APPROVAL_NODE_CHANGE_PUSH);
                    }
                } catch (Exception e) {
                    log.error("com.xbongbong.workflow.service.strategy.node.impl.WorkflowNodeApproveStrategy.addSignature message fail", e);
                }
            };
            threadPoolBeanConfig.dingtalkTodo().execute(runnable);
        }
    }
}
